﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Kiiro.Pop3Client
{
    public class MimePart
    {
        public string ContentType { get; set; }
        public string Content { get; set; }
        public Dictionary<string, string> Headers { get; set; }
        public List<MimePart> Parts { get; set; }
    } 

    public class Message
    {
        private string from;
        private string subject;
        private DateTime date;
        private string htmlBody;
        private string textBody;
        private string messageString;

        public string From
        {
            get { return from; }
            set { from = value; }
        }
        public string Subject
        {
            get { return subject; }
            set { subject = value; }
        }
        public DateTime Date
        {
            get { return date; }
            set { date = value; }
        }
        public string HtmlBody
        {
            get { return htmlBody; }
            set { htmlBody = value; }
        }
        public string TextBody
        {
            get { return textBody; }
            set { textBody = value; }
        }
        public string MessageString
        {
            get { return messageString; }
            set { messageString = value; }
        }
                
        public MimePart GetMimePart(string mimeData, string headerCTValue)
        {
            MimePart part = new MimePart();
            part.Parts = new List<MimePart>();
            part.ContentType = ParseContentType(mimeData);
            if (part.ContentType.StartsWith("multipart"))
            {
                // split into parts 
                string boundary = GetBoundary(headerCTValue);
                Regex r = new Regex(@"[\s]*--" + boundary + @"[\s.]*\n", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                string[] rawParts = r.Split(mimeData);
                part.Headers = ParseHeaders(rawParts[0]);
                for (int i = 1; i < rawParts.Length; i++)
                {
                    if (rawParts[i].Trim() != "")
                        part.Parts.Add(GetMimePart(rawParts[i], headerCTValue));
                }
            }
            else
            {
                part.Headers = ParseHeaders(mimeData);
                part.Content = mimeData.Substring(mimeData.IndexOf("\r\n\r\n"));
            }
            return part;
        }

        public string ParseHeader(string mimeMessage, string headerName)
        {
            if (!string.IsNullOrEmpty(mimeMessage) || !string.IsNullOrEmpty(headerName))
            {
                Regex r = new Regex(headerName + @":\s+(?<HeaderValue>.*\n)");
                Match m = r.Match(mimeMessage);
                if (m.Groups["HeaderValue"] != null)
                    return m.Groups["HeaderValue"].Value.Trim();
            }
            return "";
        }

        public Dictionary<string, string> ParseHeaders(string mimeMessage)
        {
            Dictionary<string, string> headers = new Dictionary<string, string>();
            if (!string.IsNullOrEmpty(mimeMessage))
            {
                Regex r = new Regex(@"(?<HeaderName>[^\r\n:]+):\s+(?<HeaderValue>(.+[\r\n][\t\x20]+.+)|(.+))");
                MatchCollection m = r.Matches(mimeMessage);
                foreach (Match match in m)
                {
                    if (!headers.ContainsKey(match.Groups["HeaderName"].Value.Trim()))
                        headers.Add(match.Groups["HeaderName"].Value.Trim(), match.Groups["HeaderValue"].Value.Trim());
                }
            }
            return headers;
        }

        public string ParseContentType(string rawData)
        {
            string contentType = ParseHeader(rawData, "Content-Type");
            if (contentType.Contains(Environment.NewLine))
            {
                contentType = contentType.Substring(0, contentType.IndexOf("\r\n")).Trim().TrimEnd(';');
            }

            //rawData.Validate("mimeData");

            Regex r = new Regex(@"Content-Type:[\s]+(?<ContentType>.*)");
            Match m = r.Match(rawData);
            return m.Groups["ContentType"].Value.Trim().Replace(";", "");
        }

        public string GetBoundary(string contentTypeValue)
        {
            Regex r = new Regex(@"(?<HeaderName>[^\r\n:]+)boundary=+(?<Boundary>(.+[\r\n][\t\x20]+.+)|(.+))");
            MatchCollection m = r.Matches(contentTypeValue);
            return m[0].Groups["Boundary"].Value.Trim('\"');
        }
    }
}
